#ifndef HASHROWIMPL_H_JM_20120910
#define HASHROWIMPL_H_JM_20120910

#include "HashRow.h"
#include "HashRowSynchronizedImpl.h"

namespace jmlib {

	/**
	* 
	* @tparam T typ ukladanych hodnot.
	**/
	template<class KeyT, class ValueT, class MutexT, class ScopedLockT>
	class HashRowImpl : public HashRow<KeyT, ValueT> {
	public:

		HashRowImpl() { synchronizedThis_.setHashRowUnsynchronized(this); }

		virtual int add(const KeyType& key, const ValueType& value) override {		
			for (size_t i = 0; i < values_.size(); ++i) {
				if (values_[i].plainEntry.key == key) {					
					values_[i].setCount(values_[i].getCount() + 1);
					return values_[i].getCount();
				}
			}
			values_.push_back(ExtendedRowEntry(key, value));
			return 1;
		}

		virtual bool hasKey(const KeyType& key) const  override {
			for (size_t i = 0; i < values_.size(); ++i) {
				if (values_[i].plainEntry.key == key) {	
					return true;
				}
			}
			return false;
		}

		virtual bool addIf(const KeyType& key, const ValueType& value, 
			const HashRowActionCondition& cond) override {
				bool addValue; 
				switch (cond) {
					case HAS_KEY:
						addValue = hasKey(key);
						break;
					case HAS_NOT_KEY:
						addValue = !hasKey(key);
						break;
					default:
						assert(false);
				}
				if (addValue) {
					add(key, value);
					return true;
				} 
				else {
					return false;
				}
		}

		virtual bool remove(const KeyType& key) override {
			for (auto it = values_.begin(); it != values_.end(); ++it) {
				if (it->plainEntry.key == key) {	
					values_.erase(it);
					return true;
				}
			}
			return false;
		}

		virtual ExtendedRowEntry getExtendedValue(const size_t& index) const override {
			return values_[index];
		}

		virtual bool isEmpty() const override {
			return values_.empty();
		}

		virtual void clear() override {
			values_.clear();
		}

	
		virtual size_t getAggregatedEntryCount() const override {
			size_t count = 0;
			for (size_t i = 0; i < values_.size(); ++i) {
					count += values_[i].getCount();
			} 
			return count;
		}


		virtual size_t getExtendedEntryCount() const override {
			return values_.size();
		}

		virtual void foreach(ForechEntryFunType functor) override {
			for (size_t i = 0; i < values_.size(); ++i) {
				for (size_t j = 0; j < values_[i].getCount(); ++j) {
					functor(values_[i].plainEntry);
				}				
			}
		}

		virtual bool applyOn(ForechEntryFunType functor, const KeyType& key) override {
			for (size_t i = 0; i < values_.size(); ++i) {
				bool found = false;
				for (size_t j = 0; j < values_[i].getCount(); ++j) {
					if (values_[i].plainEntry.key == key) {
						functor(values_[i].plainEntry);
						found = true;
					}
				}				
				if (found) return true;
			}
			return false;
		}


		virtual void foreachExtended(ForechExtendedEntryFunType functor) override {
			for (size_t i = 0; i < values_.size(); ++i) {
					functor(values_[i]);
			}
		}

		virtual bool applyOnExtended(ForechExtendedEntryFunType functor, 
			const KeyType& key) override {
				for (size_t i = 0; i < values_.size(); ++i) {
					if (values_[i].plainEntry.key == key) {
						functor(values_[i]);
						return true;
					}
				}
				return false;
		}

		virtual HashRowInterface* getLockFreeInstance() override { 
			return this; 
		};

		virtual HashRowInterface* getLockableInstance() override { 
			return &synchronizedThis_; 
		};

	private:
		/// Hodnoty v riadku
		RowEntryContainer values_;
		HashRowSynchronizedImpl<KeyType, ValueType, MutexT, ScopedLockT> synchronizedThis_;
	};

} // namespace jmlib


#endif
